Option Strict Off
Option Explicit On
Imports SlimDX
Friend Class CD3DFrame
	
	'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
	'
	'  Copyright (C) 2000 Microsoft Corporation.  All Rights Reserved.
	'
	'  File:       D3DFrame.cls
	'  Content:    D3D Visual Basic Framework Frame object
	'
	'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
	
	
	
    Public ObjectName As String = "" 'Name of object
	Public Enabled As Boolean 'True to render
	Public Selected As Boolean ' Frame Selected True/False
	Public HasSkyBox As Boolean
	Public isTerrain As Boolean
	
    Dim m_Matrix As Matrix 'local coordinate system matrix
    Dim m_MatConcat As Matrix 'world matrix coordinate system
    Dim m_MatConcatInv As Matrix 'inv world matrix
	
	Dim m_NumFrames As Integer 'Number of child frame
	Dim m_NumMesh As Integer 'Number of child mesh
	Dim m_MaxFrames As Integer 'Max number of frames before reallocation
	Dim m_MaxMesh As Integer 'Max number of meshes befor reallocation
	Dim m_DeletedFrames As Integer 'Number of frame deleted
	Dim m_DeletedMesh As Integer 'Number of mesh deleted
	
	Dim m_D3DMesh() As CD3DMesh 'List of child Meshes
	Dim m_D3DFrame() As CD3DFrame 'List of Child Frame
	
    '   Dim m_PreRenderEvent As DxVBLibA.DirectXEvent8 'Callback for prerender event
    '	Dim m_PreRenderId As Integer 'Handle to send to prerender event
    '	Dim m_PostRenderEvent As DxVBLibA.DirectXEvent8 'Callback for postrender event
    '	Dim m_PostRenderId As Integer 'Handle to send to postrender event
	
	Dim m_SphereRadius As Single 'Bounding radius
    Dim m_SphereWorldPos As Vector3 'Bounding sphere center in world coord
    Dim m_SphereModelPos As Vector3 'Bounding sphere center in local coord

    Dim m_pos As Vector3 'Position as set by SetPosition
    Dim m_quat As Quaternion 'Orientations as set by SetOrientation
    Dim m_rotcenter As Vector3 '
    Dim m_scale As Single 'Uniform scale as set by SetScale

    Const kArrayStep As Short = 5

    Public Enum CombineTypeEnum
        COMBINE_BEFORE = 0
        COMBINE_AFTER = 1
        COMBINE_replace = 2
    End Enum

    Public Enum TransformOp
        TRANSFORM_COMPUTE = 0
        TRANSFORM_FROMUPDATEFRAME = 1
        TRANSFORM_DISABLE = 2
    End Enum



    Public Sub Dispose()
        Dim i As Integer
        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then
                m_D3DFrame(i).Dispose()
                m_D3DFrame(i) = Nothing
            End If
        Next
        For i = 0 To m_NumMesh - 1
            If m_D3DMesh(i) IsNot Nothing Then
                m_D3DMesh(i).Dispose()
                m_D3DMesh(i) = Nothing
            End If
        Next

        Erase m_D3DFrame
        Erase m_D3DMesh
        m_D3DFrame = Nothing
        m_D3DMesh = Nothing
        m_NumFrames = 0
        m_NumMesh = 0
        m_SphereWorldPos = Nothing
        m_pos = Nothing
        m_rotcenter = Nothing
        m_quat = Nothing

    End Sub


    Sub AddTree(parent As System.Windows.Forms.TreeNode)

        Dim aMesh As CD3DMesh
        Dim aFrame As CD3DFrame
        Dim i As Integer
        Dim ID As Short

        Dim Nodx As System.Windows.Forms.TreeNode
        Dim Nome As String

        If parent Is Nothing Then
            If ObjectName.Length = 0 Then ObjectName = "Root"
            Nodx = UT.Nodes.Add("root", "Root", 0, 0)
            Nodx.EnsureVisible()
            parent = Nodx
        End If

        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then
                Nome = m_D3DFrame(i).ObjectName
                Nodx = parent.Nodes.Add("F-" & Nome, Nome, 1, 1)
                Nodx.EnsureVisible()
                m_D3DFrame(i).AddTree(Nodx)
            End If
        Next

        '    ID = UT.NodesCount
        For i = 0 To m_NumMesh - 1
            If m_D3DMesh(i) IsNot Nothing Then
                Nome = m_D3DMesh(i).ObjectName
                Nodx = parent.Nodes.Add("M-" & Nome, Nome, 2, 2)
                Nodx.EnsureVisible()
            End If
        Next


    End Sub


    Sub AddTree(Idx As Short)

        Dim aMesh As CD3DMesh
        Dim aFrame As CD3DFrame
        Dim i As Integer
        Dim ID As Short

        Dim Nodx As System.Windows.Forms.TreeNode
        Dim Nome As String

        If Idx = 0 Then
            Nome = "Root"
            Nodx = UT.Nodes.Add(Nome)
            Nodx.EnsureVisible()
            ID = 1 : Idx = 1
        End If


        For i = 0 To m_NumFrames - 1

            aFrame = m_D3DFrame(i)
            If aFrame IsNot Nothing Then
                Nome = aFrame.ObjectName
                Nodx = UT.Nodes(Idx - 1)
                Nodx.Nodes.Add(Nome, Nome)
                Nodx.EnsureVisible()
                ID = UT.Nodes.Count
                aFrame.AddTree(ID)
            End If
        Next

        '    ID = UT.NodesCount
        For i = 0 To m_NumMesh - 1
            aMesh = m_D3DMesh(i)
            If Not aMesh Is Nothing Then
                aMesh.AddTree(Idx)
            End If
        Next


    End Sub

    Public Sub GetLocalBox(ByRef MinExt As Vector3, ByRef MaxExt As Vector3)

        Dim aMesh As CD3DMesh
        Dim aFrame As CD3DFrame
        Dim i As Integer
        Dim mn, mx As Vector3

        For i = 0 To m_NumMesh - 1
            aMesh = m_D3DMesh(i)
            If Not aMesh Is Nothing Then
                aMesh.GetLocalBox(mn, mx)
                MinExt.x = Min((MinExt.x), (mn.x))
                MinExt.y = Min((MinExt.y), (mn.y))
                MinExt.Z = Min((MinExt.Z), (mn.Z))
                MaxExt.x = Max((MaxExt.x), (mx.x))
                MaxExt.y = Max((MaxExt.y), (mx.y))
                MaxExt.Z = Max((MaxExt.Z), (mx.Z))
            End If
        Next

        For i = 0 To m_NumFrames - 1
            aFrame = m_D3DFrame(i)
            If Not aFrame Is Nothing Then
                aFrame.GetLocalBox(mn, mx)
                MinExt.x = Min((MinExt.x), (mn.x))
                MinExt.y = Min((MinExt.y), (mn.y))
                MinExt.Z = Min((MinExt.Z), (mn.Z))
                MaxExt.x = Max((MaxExt.x), (mx.x))
                MaxExt.y = Max((MaxExt.y), (mx.y))
                MaxExt.Z = Max((MaxExt.Z), (mx.Z))
            End If
        Next
        aMesh = Nothing
        aFrame = Nothing

    End Sub

    Function GetMaterialOverride() As Direct3D9.Material

        If m_NumMesh >= 0 Then Return m_D3DMesh(0).GetMaterialOverride()

    End Function



    Sub SetMaterialOverride(material As Direct3D9.Material)

        Dim i As Integer
        Dim aMesh As CD3DMesh
        Dim aFrame As CD3DFrame

        For i = 0 To m_NumMesh - 1
            aMesh = m_D3DMesh(i)
            If Not aMesh Is Nothing Then
                aMesh.SetMaterialOverride(material)
            End If
        Next

        For i = 0 To m_NumFrames - 1
            aFrame = m_D3DFrame(i)
            If Not aFrame Is Nothing Then
                aFrame.SetMaterialOverride(material)
            End If
        Next
        aMesh = Nothing
        aFrame = Nothing

    End Sub




    '-----------------------------------------------------------------------------
    ' Name: AddChild
    ' Desc: adds another frame as a child
    '-----------------------------------------------------------------------------
    Public Sub AddChild(child As CD3DFrame)
        If m_MaxFrames = 0 Then
            m_MaxFrames = kArrayStep
            ReDim m_D3DFrame(m_MaxFrames)
        ElseIf m_MaxFrames <= m_NumFrames Then
            m_MaxFrames = m_MaxFrames + kArrayStep
            ReDim Preserve m_D3DFrame(m_MaxFrames)
        End If
        m_D3DFrame(m_NumFrames) = child
        m_NumFrames = m_NumFrames + 1
    End Sub

    '-----------------------------------------------------------------------------
    ' Name: SetPosition
    ' Desc: sets position of the object in the parents coordinate system
    ' Note: will replace whatever matrix is set
    '-----------------------------------------------------------------------------
    Sub SetPosition(vec As Vector3)
        m_pos = vec
        UpdateMatrix()
    End Sub

    '-----------------------------------------------------------------------------
    ' Name: GetPosition
    ' Desc: returns the position of the object in the parents coordinate system
    '-----------------------------------------------------------------------------
    Function GetPosition() As Vector3
        GetPosition.x = m_Matrix.m41
        GetPosition.y = m_Matrix.m42
        GetPosition.Z = m_Matrix.m43
    End Function

    '-----------------------------------------------------------------------------
    ' Name: SetOrientation
    ' Desc: sets the orientation of the object
    ' Note: use D3DXQuaternionRotationAxis to create the quaternion
    ' Note: will replace whatever matrix is set
    '-----------------------------------------------------------------------------
    Sub SetOrientation(quat As Quaternion)
        m_quat = quat
        UpdateMatrix()
    End Sub

    '-----------------------------------------------------------------------------
    ' Name: GetOrientation
    ' Desc: returns what ever was passed to SetOrientation
    ' Note: does not inspect the matrix to obtain orientation
    '-----------------------------------------------------------------------------
    Function GetOrientation() As Quaternion
        Return m_quat
    End Function


    '-----------------------------------------------------------------------------
    ' Name: SetScale
    ' Desc: Sets the uniform scale of all children
    ' Note: will replace whatever matrix is set
    '-----------------------------------------------------------------------------
    Sub SetScale(value As Single)
        m_scale = value
        UpdateMatrix()
    End Sub

    '-----------------------------------------------------------------------------
    ' Name: GetScale
    ' Desc: returns what ever was passed to SetScale
    ' Note: does not inspect the matrix to obtain scale
    '-----------------------------------------------------------------------------
    Function GetScale() As Single
        Return m_scale
    End Function



    '-----------------------------------------------------------------------------
    ' Name: SetOrientationCenter
    ' Desc: Sets the pivot point for the Frame
    ' Note: will replace whatever matrix is set
    '-----------------------------------------------------------------------------
    Sub SetOrientationCenter(vec As Vector3)
        m_rotcenter = vec
        UpdateMatrix()
    End Sub

    '-----------------------------------------------------------------------------
    ' Name: GetOrientationCenter
    ' Desc: returns whatever pivot point was set
    ' Note: does not inspect the matrix to obtain pivot
    '-----------------------------------------------------------------------------
    Function GetOrientationCenter() As Vector3
        Return m_rotcenter
    End Function


    '-----------------------------------------------------------------------------
    ' Name: AddMesh
    ' Desc: Adds a Child Mesh object to the frame
    '-----------------------------------------------------------------------------
    Public Sub AddMesh(childMesh As CD3DMesh)
        If m_MaxMesh = 0 Then
            m_MaxMesh = kArrayStep
            ReDim m_D3DMesh(m_MaxMesh)
        ElseIf m_MaxMesh <= m_NumMesh Then
            m_MaxMesh = m_MaxMesh + kArrayStep
            ReDim Preserve m_D3DMesh(m_MaxMesh)
        End If
        m_D3DMesh(m_NumMesh) = childMesh
        m_NumMesh = m_NumMesh + 1
    End Sub


    '-----------------------------------------------------------------------------
    ' Name: AddD3DXMesh
    ' Desc: Adds a D3DX mesh object to the frame
    ' Note: The d3dxmesh object is first encapuslated in a CD3DMesh object
    '-----------------------------------------------------------------------------
    Public Function AddD3DXMesh(Mesh As Primitiva) As CD3DMesh

        Dim childMesh As CD3DMesh
        childMesh = New CD3DMesh
        childMesh.InitFromPrimitive(Mesh)


        If m_MaxMesh = 0 Then
            m_MaxMesh = kArrayStep
            ReDim m_D3DMesh(m_MaxMesh)
        ElseIf m_MaxMesh <= m_NumMesh Then
            m_MaxMesh = m_MaxMesh + kArrayStep
            ReDim Preserve m_D3DMesh(m_MaxMesh)
        End If
        m_D3DMesh(m_NumMesh) = childMesh
        m_NumMesh = m_NumMesh + 1

        Return childMesh

    End Function

    Public Function AddD3DXMesh(Mesh As Direct3D9.Mesh) As CD3DMesh

        Dim childMesh As CD3DMesh
        childMesh = New CD3DMesh
        childMesh.InitFromD3DXMesh(Mesh)

        If m_MaxMesh = 0 Then
            m_MaxMesh = kArrayStep
            ReDim m_D3DMesh(m_MaxMesh)
        ElseIf m_MaxMesh <= m_NumMesh Then
            m_MaxMesh = m_MaxMesh + kArrayStep
            ReDim Preserve m_D3DMesh(m_MaxMesh)
        End If
        m_D3DMesh(m_NumMesh) = childMesh
        m_NumMesh = m_NumMesh + 1

        Return childMesh

    End Function

    '-----------------------------------------------------------------------------
    ' Name: GetMatrix
    ' Desc: Returns the matrix for the local coordinate system
    '-----------------------------------------------------------------------------
    Public Function GetMatrix() As Matrix
        GetMatrix = m_Matrix
    End Function

    '-----------------------------------------------------------------------------
    ' Name: SetMatrix
    ' Desc: Sets the matrix for the local coordinate system
    ' Note: This overrides any previous calls to functions such as
    '       SetPosition, SetScale, SetOrientation
    '-----------------------------------------------------------------------------
    Public Sub SetMatrix(m As Matrix)
        m_Matrix = m
    End Sub

    '-----------------------------------------------------------------------------
    ' Name: GetChildMeshCount
    ' Desc: returns the number of child meshes
    '-----------------------------------------------------------------------------
    Public Function GetChildMeshCount() As Integer
        Return m_NumMesh
    End Function


    '-----------------------------------------------------------------------------
    ' Name: GetChildMesh
    ' Desc: returns a given child mesh
    '-----------------------------------------------------------------------------
    Public Function GetChildMesh(i As Integer) As CD3DMesh
        Return m_D3DMesh(i)
    End Function

    '-----------------------------------------------------------------------------
    ' Name: GetChildFrame
    ' Desc: returns a given child frame
    '-----------------------------------------------------------------------------
    Public Function GetChildFrame(i As Integer) As CD3DFrame
        Return m_D3DFrame(i)
    End Function


    '-----------------------------------------------------------------------------
    ' Name: GetChildFrameCount
    ' Desc: returns number of Child Frames
    '-----------------------------------------------------------------------------
    Public Function GetChildFrameCount() As Integer
        Return m_NumFrames
    End Function



    '-----------------------------------------------------------------------------
    ' Name: FindChildObject
    ' Desc: Given an object name (flags are ignored) return the first child with
    '       a matching name. use the ClassName property to see if its a mesh
    '       or a frame object
    '-----------------------------------------------------------------------------

    Public Function FindChildObject(Name As String, flags As Integer) As Object
        Dim i As Integer
        Dim aMesh As CD3DMesh
        Dim aFrame As CD3DFrame

        'check self
        If ObjectName = Name Then Return Me

        'check child mesh
        For i = 0 To m_NumMesh - 1
            aMesh = m_D3DMesh(i)
            If aMesh IsNot Nothing Then
                If aMesh.ObjectName = Name Then Return aMesh
            End If
        Next

        Dim o As Object
        'check child frames
        For i = 0 To m_NumFrames - 1
            aFrame = m_D3DFrame(i)
            If aFrame IsNot Nothing Then
                o = aFrame.FindChildObject(Name, flags)
                If o IsNot Nothing Then Return o
            End If
        Next
        Return Nothing
    End Function

    '-----------------------------------------------------------------------------
    ' Name: FindChildParent
    ' Desc: given an object name find its parent frame
    '-----------------------------------------------------------------------------

    Public Function FindChildParent(Name As String, flags As Integer) As CD3DFrame
        Dim i As Integer
        Dim o As CD3DFrame

        'check child mesh
        For i = 0 To m_NumMesh - 1
            If m_D3DMesh(i) IsNot Nothing Then
                If m_D3DMesh(i).ObjectName = Name Then Return Me
            End If
        Next


        'check child frames
        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then
                If m_D3DFrame(i).ObjectName = Name Then Return Me
                o = m_D3DFrame(i).FindChildParent(Name, flags)
                If o IsNot Nothing Then Return o
            End If
        Next

        Return Nothing

    End Function


    '-----------------------------------------------------------------------------
    ' Name: Destroy
    ' Desc: Release all references
    '-----------------------------------------------------------------------------
    Public Sub Destroy()
        ReDim m_D3DMesh(0)
        ReDim m_D3DFrame(0)
        m_NumFrames = 0
        m_NumMesh = 0
    End Sub



    '-----------------------------------------------------------------------------
    ' Name: InitFromXOF
    ' Desc: called from InitFromFile
    '-----------------------------------------------------------------------------
    Friend Sub InitFromXOF(dev As Direct3D9.Device, FileData As DxVBLibA.DirectXFileData, parent As CD3DFrame)

        Dim ChildData As DxVBLibA.DirectXFileData
        Dim ChildObj As DxVBLibA.DirectXFileObject
        Dim TypeGuid As String
        Dim NewMesh As CD3DMesh
        Dim newFrame As CD3DFrame

        If Not parent Is Nothing Then parent.AddChild(Me)

        ObjectName = FileData.GetName()

        Do
            'list of object - should return nothing at end of list
            ChildData = FileData.GetNextObject()
            If ChildData Is Nothing Then Exit Do

            Select Case ChildData.GetType()

                Case "TID_D3DRMFrame"
                    newFrame = New CD3DFrame
                    newFrame.InitFromXOF(dev, ChildData, Me)
                    newFrame = Nothing

                Case "TID_D3DRMMesh"
                    NewMesh = New CD3DMesh
                    NewMesh.InitFromXOF(dev, ChildData)
                    AddMesh(NewMesh)
                    NewMesh = Nothing

                Case "TID_D3DRMFrameTransformMatrix"
                    ' FG 2014, poi si vede
                    'ChildData.GetDataFromOffset("", 0, Len(m_Matrix), m_Matrix)

            End Select

        Loop

    End Sub


    '-----------------------------------------------------------------------------
    ' Name: InitFromFile
    ' Desc: Called from D3DUtil_LoadFromFile
    '-----------------------------------------------------------------------------
    Public Function InitFromFile(dev As Direct3D9.Device, strFile As String, parent As CD3DFrame, animParent As CD3DAnimation) As Boolean


        Dim xFile As SlimDX.Direct3D9.XFile ' DxVBLibA.DirectXFile
        Dim enumX As SlimDX.Direct3D9.XFileEnumerationObject ' DxVBLibA.DirectXFileEnum
        Dim ChildData As SlimDX.Direct3D9.XFileData ' DxVBLibA.DirectXFileData
        Dim DataObject As SlimDX.Direct3D9.XFileData
        Dim rootid As Integer
        Dim childid As System.Guid
        Dim strPath As String
        Dim NewMesh As New CD3DMesh
        Dim newFrame As CD3DFrame



        '   On Error GoTo ErrOut


        'create the X file object
        'xFile = New SlimDX.Direct3D9.XFile ' g_dx.DirectXFileCreate()

        ''make sure it understand MeshBuilders etc
        'xFile.RegisterTemplates(Direct3D9.XFile.DefaultTemplates)

        'On Error Resume Next

        ''Open the file - will propegate file not found if fails
        'enumX = xFile.CreateEnumerationObject(strFile, Runtime.InteropServices.CharSet.Auto) 'xFile.CreateEnumObject(strFile)
        'ExtensionTemplates = "xof 0303txt 0032        template FVFData         {             <B6E70A0E-8EF9-4e83-94AD-ECC8B0C04897>             DWORD dwFVF;             DWORD nDWords;             array DWORD data[nDWords];         }         template VertexElement         {             ...
        If NewMesh.InitFromFile(g_dev, strFile) = False Then Return False
        AddMesh(NewMesh)
        NewMesh = Nothing
        If Not parent Is Nothing Then parent.AddChild(Me)

        Return True



        '  DataObject = enumX.GetDataObject("") ' .GetDataObject("B6E70A0E-8EF9-4e83-94AD-ECC8B0C04897") non si sa che cazzo vuole qui

        '        DataObject.Name

        '        'Inspect each top level object in the file
        '        For i As Integer = 0 To enumX.ChildCount - 1
        '            ChildData = enumX.GetChild(i) ''enumX.GetNextDataObject()
        '            If ChildData Is Nothing Then Exit For



        '            If ChildData.GetType = "TID_D3DRMFrame" Then
        '                newFrame = New CD3DFrame
        '                newFrame.InitFromXOF(dev, ChildData, Me)
        '                newFrame = Nothing

        '            ElseIf ChildData.GetType = "TID_D3DRMMesh" Then
        '                NewMesh = New CD3DMesh
        '                NewMesh.InitFromXOF(dev, ChildData)
        '                AddMesh(NewMesh)
        '                NewMesh = Nothing

        '            ElseIf ChildData.GetType = "TID_D3DRMAnimationSet" Then
        '                'TODO Parse Animation Set Data
        '                If Not animParent Is Nothing Then
        '                    animParent.ParseAnimSet(ChildData, Me)
        '                End If
        '            ElseIf ChildData.GetType = "TID_D3DRMMaterialSet" Then
        '                'TODO Parse TopLevel Material Data
        '            End If
        '        Loop

        '        If Not parent Is Nothing Then
        '            parent.AddChild(Me)
        '        End If
        '        On Error GoTo 0

        '        InitFromFile = True
        '        Exit Function

        'ErrOut:
        '        InitFromFile = False

    End Function


    Public Sub LoadEffect(File As String)

        Dim i As Integer

        For i = 0 To m_NumMesh - 1
            If m_D3DMesh(i) IsNot Nothing Then m_D3DMesh(i).LoadEffect(File)
        Next

        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then m_D3DFrame(i).LoadEffect(File)
        Next

    End Sub


    '-----------------------------------------------------------------------------
    ' Name: SetFVF
    ' Desc: Changes the Flexible Vertex Format of all child objects
    '-----------------------------------------------------------------------------
    Public Sub SetFVF(dev As Direct3D9.Device, fvf As Integer)

        Dim i As Integer

        For i = 0 To m_NumMesh - 1
            If m_D3DMesh(i) IsNot Nothing Then m_D3DMesh(i).SetFVF(dev, fvf)
        Next

        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then m_D3DFrame(i).SetFVF(dev, fvf)
        Next

    End Sub


    '-----------------------------------------------------------------------------
    ' Name: FlipNormals
    ' Desc: Flips the normals on all child objects (provided they are of D3DFVF_VERTEX)
    '-----------------------------------------------------------------------------
    Public Sub FlipNormals()
        Dim i As Integer

        For i = 0 To m_NumMesh - 1
            If m_D3DMesh(i) IsNot Nothing Then m_D3DMesh(i).FlipNormals()
        Next

        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then m_D3DFrame(i).FlipNormals()
        Next

    End Sub


    '-----------------------------------------------------------------------------
    ' Name: ComputeNormals
    ' Desc: Computes normals on all child objects (provided they have a normal set set)
    '-----------------------------------------------------------------------------
    Public Sub ComputeNormals()
        Dim i As Integer
        For i = 0 To m_NumMesh - 1
            If m_D3DMesh(i) IsNot Nothing Then m_D3DMesh(i).ComputeNormals()
        Next

        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then m_D3DFrame(i).ComputeNormals()
        Next

    End Sub


    '-----------------------------------------------------------------------------
    ' Name: Optimize
    ' Desc:
    '-----------------------------------------------------------------------------
    Public Sub Optimize()
        
        Dim i As Integer

        For i = 0 To m_NumMesh - 1
            If m_D3DMesh(i) IsNot Nothing Then m_D3DMesh(i).Optimize()
        Next

        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then m_D3DFrame(i).Optimize()
        Next

    End Sub



    '-----------------------------------------------------------------------------
    ' Name: ComputeBoundingVolumes
    ' Desc: ComputesBoundingVolumes for all child objects
    '-----------------------------------------------------------------------------
    Public Sub ComputeBoundingVolumes()

        
        Dim i As Integer

        For i = 0 To m_NumMesh - 1
            If m_D3DMesh(i) IsNot Nothing Then m_D3DMesh(i).ComputeBoundingVolumes()
        Next

        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then m_D3DFrame(i).ComputeBoundingVolumes()
        Next

    End Sub


    Private Sub SetSkyBox(Mode As Short)


        ' Center view matrix for skybox and disable zbuffer
        Static matView, matViewSave As Matrix
        Dim mx, v, mn As Vector3

        '        Select Case Mode
        '         Case 0
        '            g_dev.SetRenderState D3DRS_LIGHTING, 0
        '          '  g_dev.GetTransform D3DTS_VIEW, matViewSave
        '            matViewSave = m_Matrix
        '            UC.GetCameraView v.x, v.y, v.Z
        '            matView = matViewSave
        '          '  GetLocalBox mn, mx
        '          '  SetOrientationCenter v
        '            AddRotation COMBINE_replace, 0, 0, 0, 0
        '            matView.m41 = v.x: matView.m42 = v.y - 1: matView.m43 = v.Z + 1 '- 3
        '
        '           ' g_dev.SetTransform D3DTS_VIEW, matView
        '            m_Matrix = matView
        '            g_dev.SetRenderState D3DRS_ZENABLE, False
        '            ' Some cards do not disable writing to Z when
        '            ' D3DRS_ZENABLE is FALSE. So do it explicitly
        '            g_dev.SetRenderState D3DRS_ZWRITEENABLE, 0'
        '
        '            ' Render the skybox
        '           ' Render( m_pd3dDevice );'''
        '
        '            ' Restore the render states
        '          Case 1
        '           ' g_dev.SetTransform D3DTS_VIEW, matViewSave
        '            m_Matrix = matViewSave
        '            g_dev.SetRenderState D3DRS_ZENABLE, 1
        '            g_dev.SetRenderState D3DRS_ZWRITEENABLE, 1
        '            g_dev.SetRenderState D3DRS_LIGHTING, 1
        '        End Select



        Select Case Mode
            Case 0
                g_dev.SetRenderState(Direct3D9.RenderState.Lighting, 0)
                matViewSave = g_dev.GetTransform(Direct3D9.TransformState.View)
                matView = matViewSave
                matView.M41 = 0 : matView.M42 = -0.3 : matView.M43 = 0
                g_dev.SetTransform(Direct3D9.TransformState.View, matView)
                g_dev.SetRenderState(Direct3D9.RenderState.ZEnable, False) ' FALSE
                g_dev.SetRenderState(Direct3D9.RenderState.ZWriteEnable, False)

                ' Render the skybox
                ' m_SkyBox.Render g_dev
            Case 1
                ' Restore the render states
                g_dev.SetTransform(Direct3D9.TransformState.View, matViewSave)
                g_dev.SetRenderState(Direct3D9.RenderState.ZEnable, True)
                g_dev.SetRenderState(Direct3D9.RenderState.ZWriteEnable, True)
                g_dev.SetRenderState(Direct3D9.RenderState.Lighting, True)
        End Select
    End Sub

    Private Sub SetSkyBox2(ByRef Mode As Short)
        ' Center view matrix for skybox and disable zbuffer
        Static matView, matViewSave As Matrix
        Dim mx, v, mn As Vector3

        Select Case Mode
            Case 0
                g_dev.SetRenderState(Direct3D9.RenderState.Lighting, 0)
                '  g_dev.GetTransform D3DTS_VIEW, matViewSave
                matViewSave = m_Matrix
                UC.GetCameraView(v.x, v.y, v.Z)
                matView = matViewSave
                '  GetLocalBox mn, mx
                '  SetOrientationCenter v
                AddRotation(CombineTypeEnum.COMBINE_replace, 0, 0, 0, 0)
                matView.m41 = v.x : matView.m42 = v.y - 1 : matView.m43 = v.Z + 1 '- 3

                ' g_dev.SetTransform D3DTS_VIEW, matView
                m_Matrix = matView
                g_dev.SetRenderState(Direct3D9.RenderState.ZEnable, False)
                ' Some cards do not disable writing to Z when
                ' D3DRS_ZENABLE is FALSE. So do it explicitly
                g_dev.SetRenderState(Direct3D9.RenderState.ZWriteEnable, False)

                ' Render the skybox
                ' Render( m_pd3dDevice );

                ' Restore the render states
            Case 1
                ' g_dev.SetTransform D3DTS_VIEW, matViewSave
                m_Matrix = matViewSave
                g_dev.SetRenderState(Direct3D9.RenderState.ZEnable, True)
                g_dev.SetRenderState(Direct3D9.RenderState.ZWriteEnable, True)
                g_dev.SetRenderState(Direct3D9.RenderState.Lighting, True)
        End Select

    End Sub

    '-----------------------------------------------------------------------------
    ' Name: UpdateFrames
    ' Desc: Called to precompute the WorldMatrices for each child object
    ' Note: Must be used prior to calling Mesh.RenderSkin
    '-----------------------------------------------------------------------------
    Public Sub UpdateFrames()
        ' ex g_IdentityMatrix
        ComputeChildMatricesEx(g_identityMatrix)
    End Sub

    '-----------------------------------------------------------------------------
    ' Name: GetUpdatedMatrix
    ' Desc: Returns the precomputed matrix
    '-----------------------------------------------------------------------------
    Public Function GetUpdatedMatrix() As Matrix
        Return m_MatConcat
    End Function


    '-----------------------------------------------------------------------------
    ' Name: ComputeChildMatricesEx
    ' Desc: Aux function for UpdateFrames
    '-----------------------------------------------------------------------------
    Private Sub ComputeChildMatricesEx(matSavedWorld As Matrix)
        Dim i As Integer

        m_MatConcat = m_Matrix * matSavedWorld
        m_MatConcatInv = Matrix.Invert(m_MatConcat)
        'Call DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixMultiply(m_MatConcat, m_Matrix, matSavedWorld)
        'Call DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixInverse(m_MatConcatInv, det, m_MatConcat)

        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then m_D3DFrame(i).ComputeChildMatricesEx(m_MatConcat)
        Next

    End Sub





    '-----------------------------------------------------------------------------
    ' Name: RenderEx
    ' Desc: Render Child Objects
    ' Params:
    '       dev                     Device to render to
    '       bDrawOpaqueSubsets      Render all objects with an material alpha of 1
    '       bDrawAlphaSubsets       Render all objects with transparent alpha
    '       transform
    '                               TRANSFORM_COMPUTE indicates to calculate world matrix
    '                               TRANSFORM_FROMUPDATEFRAME inidcates to use precomputed matrix
    '                               TRANSFORM_DISABLE does not set any world matrix
    '                               and uses what ever has been currently set
    '-----------------------------------------------------------------------------
    Friend Sub RenderEx(dev As Direct3D9.Device, bDrawOpaqueSubsets As Boolean, bDrawAlphaSubsets As Boolean, transform As TransformOp)

        Dim matSavedWorld As Matrix
        Dim matWorld As Matrix


        Dim vCenter As Vector3

        Dim mS1, mS2 As Integer

        If Not Enabled Then Return

        If HasSkyBox Then SetSkyBox(0)

        If Selected Then
            mS1 = g_dev.GetRenderState(Direct3D9.RenderState.ShadeMode)
            mS2 = g_dev.GetRenderState(Direct3D9.RenderState.FillMode)
            g_dev.SetRenderState(Direct3D9.RenderState.ShadeMode, Direct3D9.ShadeMode.Flat)
            g_dev.SetRenderState(Direct3D9.RenderState.FillMode, Direct3D9.FillMode.Wireframe)
        End If

        Dim i As Integer


        If transform = TransformOp.TRANSFORM_COMPUTE Then
            matSavedWorld = g_dev.GetTransform(Direct3D9.TransformState.World)
            matWorld = m_Matrix * matSavedWorld
            g_dev.SetTransform(Direct3D9.TransformState.World, matWorld)
            'Call DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixMultiply(matWorld, m_Matrix, matSavedWorld)
            'Call g_dev.SetTransform(Direct3D9.TransformState.World, matWorld)
        ElseIf transform = TransformOp.TRANSFORM_FROMUPDATEFRAME Then
            g_dev.SetTransform(Direct3D9.TransformState.World, m_MatConcat)
        End If




        For i = 0 To m_NumMesh - 1

            If m_D3DMesh(i) IsNot Nothing Then
                With m_D3DMesh(i)
                    If g_bClipMesh And .bHasSphere Then
                        vCenter = Vector3.TransformCoordinate(.SphereCenter, matWorld)
                        '  DxVBLibA.D3DXMATH_VECTOR3.D3DXVec3TransformCoord(vCenter, aMesh.SphereCenter, matWorld)
                        If D3DUtil_IsSphereVisible(vCenter, .SphereRadius) <> 0 Then
                            .RenderEx(g_dev, bDrawOpaqueSubsets, bDrawAlphaSubsets)
                        Else
                            'Debug.Print "cull " + aMesh.ObjectName
                        End If
                    Else
                        .RenderEx(g_dev, bDrawOpaqueSubsets, bDrawAlphaSubsets)
                    End If
                End With
            End If
        Next

        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then m_D3DFrame(i).RenderEx(g_dev, bDrawOpaqueSubsets, bDrawAlphaSubsets, transform)
        Next

        If transform = TransformOp.TRANSFORM_COMPUTE Then
            g_dev.SetTransform(Direct3D9.TransformState.World, matSavedWorld)
        End If

        'If Not m_PostRenderEvent Is Nothing Then
        '    m_PostRenderEvent.DXCallback(m_PostRenderId)
        'End If

        ' restore rendere mode of the object if selected
        If Selected Then
            g_dev.SetRenderState(Direct3D9.RenderState.ShadeMode, mS1)
            g_dev.SetRenderState(Direct3D9.RenderState.FillMode, mS2)
        End If


        If HasSkyBox Then SetSkyBox(1) ' restore previous matrix

        matWorld = Nothing
        matSavedWorld = Nothing

    End Sub




    '-----------------------------------------------------------------------------
    ' Name: RenderSkins
    ' Desc: Searches the children for any mesh with skinned objects
    '       and renders them
    ' Note: BoneMatrice must be precalulated before rendering
    '       and bones must also be attached to appropriate mesh
    '-----------------------------------------------------------------------------
    Friend Sub RenderSkins()
        Dim i As Integer
        

        'If Not m_PreRenderEvent Is Nothing Then
        '    m_PreRenderEvent.DXCallback(m_PreRenderId)
        'End If

        For i = 0 To m_NumMesh - 1
            If m_D3DMesh(i) IsNot Nothing Then m_D3DMesh(i).RenderSkin()
        Next

        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then m_D3DFrame(i).RenderSkins()
        Next

        'If Not m_PostRenderEvent Is Nothing Then
        '    m_PostRenderEvent.DXCallback(m_PostRenderId)
        'End If

    End Sub

    '-----------------------------------------------------------------------------
    ' Name: AttatchBonesToMesh
    ' Desc:
    '-----------------------------------------------------------------------------
    Friend Sub AttatchBonesToMesh(parent As CD3DFrame)

        Dim i As Integer




        For i = 0 To m_NumMesh - 1
            If m_D3DMesh(i) IsNot Nothing Then m_D3DMesh(i).AttatchBonesToMesh(parent)
        Next

        For i = 0 To m_NumFrames - 1
            If m_D3DFrame(i) IsNot Nothing Then m_D3DFrame(i).AttatchBonesToMesh(parent)
        Next

    End Sub

    '-----------------------------------------------------------------------------
    ' Name: Render
    ' Desc: render all child objects
    '-----------------------------------------------------------------------------
    Public Sub Render(dev As Direct3D9.Device)

        dev.SetTransform(Direct3D9.TransformState.World, g_identityMatrix)


        'Render opaque subsets in  the meshes

        RenderEx(g_dev, True, False, TransformOp.TRANSFORM_COMPUTE)

        dev.SetRenderState(Direct3D9.RenderState.AlphaBlendEnable, True)
        dev.SetRenderState(Direct3D9.RenderState.SourceBlend, True)
        dev.SetRenderState(Direct3D9.RenderState.SourceBlendAlpha, True)
        dev.SetRenderState(Direct3D9.RenderState.BlendOperationAlpha, True)  '  DxVBLibA.CONST_D3DRENDERSTATETYPE.D3DRS_SRCBLEND, DxVBLibA.CONST_D3DBLEND.D3DBLEND_SRCALPHA,
        dev.SetRenderState(Direct3D9.RenderState.DestinationBlend, 6) ' DxVBLibA.CONST_D3DRENDERSTATETYPE.D3DRS_DESTBLEND, DxVBLibA.CONST_D3DBLEND.D3DBLEND_INVSRCALPHA


        dev.SetTransform(Direct3D9.TransformState.World, g_identityMatrix)

        'Render alpha subsets in  the meshes

        RenderEx(g_dev, False, True, TransformOp.TRANSFORM_COMPUTE)

        dev.SetRenderState(Direct3D9.RenderState.AlphaBlendEnable, False)


    End Sub


    '-----------------------------------------------------------------------------
    ' Name: ClassName
    '-----------------------------------------------------------------------------
    Public Function ClassName() As String
        Return "CD3DFrame"
    End Function


 
    Public Sub New()
        MyBase.New()
        m_Matrix = Matrix.Identity
        g_identityMatrix = Matrix.Identity
        m_quat = Quaternion.Identity

        'DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixIdentity(m_Matrix)
        'DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixIdentity(g_identityMatrix)

        'Call DxVBLibA.D3DXMATH_QUATERNION.D3DXQuaternionIdentity(m_quat)
        m_scale = 1
        Enabled = True
    End Sub

    '-----------------------------------------------------------------------------
    ' Name: AddRotation
    ' Param:
    '       combinetype     PreMultiply/PostMultiply/or replace current matrix
    '       x,y,z           axis of rotation
    '       rot             radians to rotate
    '-----------------------------------------------------------------------------
    Public Sub AddRotation(combinetype As CombineTypeEnum, x As Single, y As Single, Z As Single, rot As Single)

        Dim mat As New Matrix
        mat = Matrix.RotationAxis(vec3(x, y, Z), rot)
        ' DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixRotationAxis(mat, vec3(x, y, Z), rot)

        Select Case combinetype
            Case CombineTypeEnum.COMBINE_BEFORE
                m_Matrix = mat * m_Matrix
                ' DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixMultiply(m_Matrix, mat, m_Matrix)
            Case CombineTypeEnum.COMBINE_AFTER
                m_Matrix = m_Matrix * mat
                ' DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixMultiply(m_Matrix, m_Matrix, mat)
            Case CombineTypeEnum.COMBINE_replace
                m_Matrix = mat
        End Select


    End Sub


    '-----------------------------------------------------------------------------
    ' Name: AddScale
    ' Param:
    '       combinetype     PreMultiply/PostMultiply/or replace current matrix
    '       x,y,z           scale
    '-----------------------------------------------------------------------------
    Public Sub AddScale(combinetype As CombineTypeEnum, x As Single, y As Single, Z As Single)

        Dim mat As New Matrix
        mat = Matrix.Scaling(x, y, Z)

        ' DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixScaling(mat, x, y, Z)
        Select Case combinetype
            Case CombineTypeEnum.COMBINE_BEFORE
                m_Matrix = mat * m_Matrix
                ' DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixMultiply(m_Matrix, mat, m_Matrix)
            Case CombineTypeEnum.COMBINE_AFTER
                m_Matrix = m_Matrix * mat
                ' DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixMultiply(m_Matrix, m_Matrix, mat)
            Case CombineTypeEnum.COMBINE_replace
                m_Matrix = mat
        End Select

    End Sub

    '-----------------------------------------------------------------------------
    ' Name: AddTranslation
    ' Param:
    '       combinetype     PreMultiply/PostMultiply/or replace current matrix
    '       x,y,z           translation
    '-----------------------------------------------------------------------------
    Public Sub AddTranslation(combinetype As CombineTypeEnum, x As Single, y As Single, Z As Single)


        Dim mat As New Matrix
        mat = Matrix.Translation(x, y, Z)

        ' DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixTranslation(mat, x, y, Z)
        Select Case combinetype
            Case CombineTypeEnum.COMBINE_BEFORE
                m_Matrix = mat * m_Matrix
                ' DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixMultiply(m_Matrix, mat, m_Matrix)
            Case CombineTypeEnum.COMBINE_AFTER
                m_Matrix = m_Matrix * mat
                ' DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixMultiply(m_Matrix, m_Matrix, mat)
            Case CombineTypeEnum.COMBINE_replace
                m_Matrix = mat
        End Select

    End Sub


    '-----------------------------------------------------------------------------
    ' Name: TransformCoord
    ' Desc: Transform a vector by the pre-computed matrix
    '-----------------------------------------------------------------------------
    Public Function TransformCoord(vIn As Vector3) As Vector3
        Dim vOut As New Vector3
        vOut = Vector3.TransformCoordinate(vIn, m_MatConcat)
        ' DxVBLibA.D3DXMATH_VECTOR3.D3DXVec3TransformCoord(vOut, vIn, m_MatConcat)
        Return vOut
    End Function

    '-----------------------------------------------------------------------------
    ' Name: TransformNormal
    ' Desc: Transform a normal by the pre-computed matrix
    '-----------------------------------------------------------------------------
    Public Function TransformNormal(vIn As Vector3) As Vector3
        Dim vOut As New Vector3
        vOut = Vector3.TransformNormal(vIn, m_MatConcat)
        ' DxVBLibA.D3DXMATH_VECTOR3.D3DXVec3TransformNormal(vOut, vIn, m_MatConcat)
        Return vOut
    End Function


    '-----------------------------------------------------------------------------
    ' Name: InverseTransformCoord
    ' Desc: Transform a vector by the inverse of the pre-computed matrix
    '-----------------------------------------------------------------------------
    Public Function InverseTransformCoord(vIn As Vector3) As Vector3
        Dim vOut As New Vector3
        vOut = Vector3.TransformCoordinate(vIn, m_MatConcatInv)
        ' DxVBLibA.D3DXMATH_VECTOR3.D3DXVec3TransformCoord(vOut, vIn, m_MatConcatInv)
        Return vOut
    End Function

    '-----------------------------------------------------------------------------
    ' Name: InverseTransformNormal
    ' Desc: Transform a normal by the inverse of the pre-computed matrix
    '-----------------------------------------------------------------------------
    Public Function InverseTransformNormal(vIn As Vector3) As Vector3
        Dim vOut As New Vector3
        vOut = Vector3.TransformNormal(vIn, m_MatConcatInv)
        ' DxVBLibA.D3DXMATH_VECTOR3.D3DXVec3TransformNormal(vOut, vIn, m_MatConcatInv)
        Return vOut
    End Function
	
	
	'-----------------------------------------------------------------------------
	' Name: InvalidateDeviceObjects
	' Desc:
	'-----------------------------------------------------------------------------
	Public Sub InvalidateDeviceObjects()
		'all objects are managed so nothing to do
	End Sub
	
	
	'-----------------------------------------------------------------------------
	' Name: RestoreDeviceObjects
	' Desc:
	'-----------------------------------------------------------------------------
    Public Sub RestoreDeviceObjects(ByRef dev As Direct3D9.Device)
        'all objects are managed so nothing to do
    End Sub
	
	
	'-----------------------------------------------------------------------------
	' Name: UpdateMatrix
	' Desc: Aux function for SetPosition, SetOrientation, SetScale
	'-----------------------------------------------------------------------------
	Private Sub UpdateMatrix()
        Try
            m_Matrix = Matrix.AffineTransformation(m_scale, m_rotcenter, m_quat, m_pos)
        Catch ex As Exception

        End Try



        'DxVBLibA.D3DXMATH_MATRIX.D3DXMatrixAffineTransformation(m_Matrix, m_scale, m_rotcenter, m_quat, m_pos)
    End Sub
End Class